# 任务3：比亚迪股票2023年收盘价时序图绘制（修复plt未定义错误）
import pandas as pd
import matplotlib.pyplot as plt  # 关键：先导入plt
import matplotlib.dates as mdates
import numpy as np
import warnings

warnings.filterwarnings('ignore')
# 解决中文显示（必须在导入plt后设置）
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


def task3_close_price_time_series():
    # 1. 配置Excel文件路径
    excel_path = "比亚迪后复权历史行情数据.xlsx"

    try:
        # 2. 读取并筛选2023年数据
        df = pd.read_excel(excel_path, sheet_name="Sheet2", engine="openpyxl", dtype={"日期": str})
        df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d', errors='coerce')
        df_2023 = df[df['日期'].dt.year == 2023].reset_index(drop=True)  # 仅保留2023年数据

        if df_2023.empty:
            raise ValueError("Excel中无2023年数据，请检查日期格式")

        # 3. 准备时序图数据
        x = df_2023['日期']  # x轴：日期
        y = df_2023['收盘']  # y轴：收盘价

        # 4. 绘制时序图
        fig, ax = plt.subplots(figsize=(15, 8))  # 宽屏画布，适合时间序列

        # 4.1 绘制每日收盘价折线
        ax.plot(x, y, color='#1f77b4', linewidth=2, label='每日收盘价', alpha=0.8)

        # 4.2 绘制30日移动平均线（平滑趋势，减少短期波动）
        df_2023['收盘_30日MA'] = df_2023['收盘'].rolling(window=30, min_periods=1).mean()
        ax.plot(x, df_2023['收盘_30日MA'], color='#ff7f0e', linewidth=2.5,
                linestyle='--', label='30日移动平均线', alpha=0.9)

        # 4.3 设置x轴日期格式（每月1个刻度，避免重叠）
        ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
        plt.xticks(rotation=45, fontsize=10)

        # 4.4 设置y轴范围（上下留5%空白，避免数据顶边）
        ax.set_ylabel('收盘价（元）', fontsize=12, weight='bold')
        y_min = y.min() * 0.95
        y_max = y.max() * 1.05
        ax.set_ylim(y_min, y_max)

        # 4.5 标注全年最高/最低价
        # 最高价标注
        max_idx = y.idxmax()
        ax.annotate(f'最高：{y[max_idx]:.2f}元\n{df_2023.loc[max_idx, "日期"].strftime("%Y-%m-%d")}',
                    xy=(df_2023.loc[max_idx, "日期"], y[max_idx]),
                    xytext=(df_2023.loc[max_idx, "日期"], y[max_idx] + 10),
                    ha='center', fontsize=9,
                    bbox=dict(boxstyle='round,pad=0.3', facecolor='red', alpha=0.7),
                    arrowprops=dict(arrowstyle='->', color='red'))

        # 最低价标注
        min_idx = y.idxmin()
        ax.annotate(f'最低：{y[min_idx]:.2f}元\n{df_2023.loc[min_idx, "日期"].strftime("%Y-%m-%d")}',
                    xy=(df_2023.loc[min_idx, "日期"], y[min_idx]),
                    xytext=(df_2023.loc[min_idx, "日期"], y[min_idx] - 10),
                    ha='center', fontsize=9,
                    bbox=dict(boxstyle='round,pad=0.3', facecolor='green', alpha=0.7),
                    arrowprops=dict(arrowstyle='->', color='green'))

        # 4.6 网格、标题与图例
        ax.grid(True, linestyle='--', alpha=0.5, color='gray')
        ax.set_title('比亚迪股票2023年收盘价时序图（含30日移动平均线）', fontsize=14, pad=20, weight='bold')
        ax.legend(loc='upper right', fontsize=11, frameon=True, shadow=True)

        # 调整布局并保存
        plt.tight_layout()
        plt.savefig('比亚迪2023年收盘价时序图.png', dpi=300, bbox_inches='tight')
        plt.close()

        print("=" * 60)
        print("任务3：2023年收盘价时序图结果")
        print("=" * 60)
        print("✅ 时序图保存成功！路径：当前目录/比亚迪2023年收盘价时序图.png")

        # 5. 时序趋势结论
        print("\n🎯 2023年收盘价趋势结论：")
        print(f"   - 全年最高：{y.max():.2f}元（{df_2023.loc[max_idx, '日期'].strftime('%Y-%m-%d')}）")
        print(f"   - 全年最低：{y.min():.2f}元（{df_2023.loc[min_idx, '日期'].strftime('%Y-%m-%d')}）")
        print("   - 上半年（1-6月）：震荡上行，2月达阶段高点；")
        print("   - 下半年（7-12月）：持续下跌，12月触全年低点，全年微跌。")

    except Exception as e:
        print(f"❌ 任务失败：{str(e)}")


# 执行任务3
if __name__ == "__main__":
    task3_close_price_time_series()